<?php

declare(strict_types=1);

namespace app\api\controller;

use think\facade\Request;
use think\facade\Db;




class Withdrawal
{
    public $data = [];
    public function __construct()
    {
        //公众号appid
        $this->data['mch_appid'] = '公众号appid';
        //商户号 
        $this->data['mchid'] = '商户号';
        // 商户支付密钥
        $this->data['api_key'] = '商户支付密钥';
        //随机字符串 
        $this->data['nonce_str'] = 'pay' . mt_rand(100, 999);
        //不检验用户姓名  
        $this->data['check_name'] = 'NO_CHECK';
        //获取IP  
        $this->data['spbill_create_ip'] = $_SERVER['SERVER_ADDR'];
        //商户密钥 
        $this->data['key'] = '';
        //商户证书 商户平台的API安全证书下载
        // $this->data['apiclient_cert.pem'];
        // $this->data['apiclient_key.pem'];
    }
    /**
     * 用户提现信息列表
     */
    public function list()
    {
        $openid = Request::header('openid');
        $page = Request::param('page');
        $page_size = Request::param('page_size');
        $uid = Db::name('user')->where('wechat_openid', $openid)->find()['uid'];
        $list = Db::name('withdrawal')->where(array('uid' => $uid))->order('update_time', 'desc');
        $total = $list->select()->count();
        // $order = $list->page((int)$page, (int)$page_size)->select();
        $order = $list->page((int)$page, (int)$page_size)->select()->each(function ($item, $key) {
            $item['type'] = 2;
            return $item;
        });
        $data = [
            'data' => $order,
            'total' => $total
        ];
        return jsonData(1, '查询成功', $data);
    }

    /**
     * 创建提现订单
     */
    public function create($order)
    {
        $oid = Db::name('order')->where('order_sn', $order['out_trade_no'])->find()['id'];
        // 通过传过来的支付成功订单号，判断是否存在已创建的提现订单
        $wid = Db::name('withdrawal')->where('oid', $oid)->find();
        if (!$wid) {
            $uid = Db::name('user')->where('wechat_openid', $order['openid'])->find()['uid'];
            // 订单实付金额
            $money = $order['total_fee'] / 100;
            // 订单信息
            $data = [
                'uid' => $uid,
                'oid' => $oid,
                'order_money' => $money,
                'withdrawal_money' => $money * 0.994,
                'order_sn' => get_sn(),
                'create_time' => time(),
                'update_time' => time(),
                'status' => 0,
            ];
            Db::name('withdrawal')->insert($data);
            $wid = Db::name('withdrawal')->where('order_sn', $data['order_sn'])->find()['id'];
            // 发起提现
            $this->userpay($wid);
        }
    }

    /**
     **开始支付
     */
    public function userpay($wid)
    {
        // $oid = Request::param('oid');
        $order = Db::name('withdrawal')->where('id', $wid)->find();
        $openid = Db::name('user')->where('uid', $order['uid'])->find()['wechat_openid'];
        $money = $order['withdrawal_money'];
        $trade_no = $order['order_sn'];
        $res = $this->pay($openid, $trade_no, $money, '微信提现');
        //结果打印
        if ($res['result_code'] == "SUCCESS") {
            // 提现成功，更新数据库
            $pay_data['status'] = 1;
            $pay_data['update_time'] = time();
            Db::name('withdrawal')->where(array('order_sn' => $res['partner_trade_no'], 'status' => 0))->update($pay_data);
            return jsonData(1, '提现成功');
        } else {
            // 存入提现失败原因
            $pay_data['err_msg'] = $res['err_code'];
            $pay_data['update_time'] = time();
            Db::name('withdrawal')->where(array('order_sn' => $res['partner_trade_no'], 'status' => 0))->update($pay_data);
            return jsonData(0, '提现失败，错误代码：' . $res['err_code']);
        }
    }

    /**
     *支付方法
     */
    public function pay($openid, $trade_no, $money, $desc)
    {
        $params["mch_appid"] = $this->data['mch_appid'];
        $params["mchid"] = $this->data['mchid'];
        $params["api_key"] = $this->data['api_key'];
        $params["nonce_str"] = 'pay' . mt_rand(100, 999);
        $params["partner_trade_no"] = $trade_no;
        $params["amount"] = $money * 100;
        $params["desc"] = $desc;
        $params["openid"] = $openid;
        $params["check_name"] = 'NO_CHECK';
        // $params['spbill_create_ip'] = $_SERVER['SERVER_ADDR'];

        //生成签名
        $str = 'amount=' . $params["amount"] . '&check_name=' . $params["check_name"] . '&desc=' . $params["desc"] . '&mch_appid=' . $params["mch_appid"] . '&mchid=' . $params["mchid"] . '&nonce_str=' . $params["nonce_str"] . '&openid=' . $params["openid"] . '&partner_trade_no=' . $params["partner_trade_no"] . '&key=' . $params["api_key"];

        //md5加密 转换成大写
        $sign = strtoupper(md5($str));
        //生成签名
        $params['sign'] = $sign;

        //构造XML数据
        $xmldata = $this->array_to_xml($params); //数组转XML

        // var_dump($xmldata);
        // die;
        $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';

        //发送post请求
        $res = $this->curl_post_ssl($url, $xmldata); //curl请求 
        if (!$res) {
            return array(
                'status' => 1,
                'msg' => "服务器连接失败"
            );
        }

        //付款结果分析
        $content = $this->xml_to_array($res); //xml转数组
        return $content;
    }

    /**
     * curl请求
     */
    public function curl_post_ssl($url, $xmldata,  $second = 30, $aHeader = array())
    {


        // var_dump($cert_dir);
        // die;
        $ch = curl_init();
        //超时时间
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        //这里设置代理，如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '10.206.30.98');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

        //默认格式为PEM，可以注释
        curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
        $cert_dir = $_SERVER['DOCUMENT_ROOT'] . '/cert/';
        //绝对地址可使用 dirname(__DIR__)打印，如果不是绝对地址会报 58 错误
        curl_setopt($ch, CURLOPT_SSLCERT, $cert_dir . 'apiclient_cert.pem');
        curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
        curl_setopt($ch, CURLOPT_SSLKEY, $cert_dir . 'apiclient_key.pem');
        if (count($aHeader) >= 1) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
        }
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xmldata);
        $data = curl_exec($ch);
        if ($data) {
            curl_close($ch);
            return $data;
        } else {
            $error = curl_errno($ch);
            echo "call faild, errorCode:$error\n";
            die();
            curl_close($ch);
            return false;
        }
    }

    /**
     * array 转 xml
     * 用于生成签名
     */
    public function array_to_xml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
        }
        $xml .= "</xml>";
        return $xml;
    }

    /**
     * xml 转化为array
     */
    public function xml_to_array($xml)
    {
        // var_dump($xml);
        // die;
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $values;
    }
}
